package com.budwk.app.util.poiUtils;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.budwk.app.oss.models.SysOss;
import com.budwk.app.oss.services.SysOssService;
import com.budwk.app.sqfw.component.CommonComponent;
import com.budwk.app.util.poiUtils.nutzBeanUtils.NutzIocUtils;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.zip.ParallelScatterZipCreator;
import org.apache.commons.compress.archivers.zip.UnixStat;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.parallel.InputStreamSupplier;
import org.apache.commons.io.input.NullInputStream;
import org.apache.commons.lang3.StringUtils;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.mvc.upload.TempFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author LJT
 * @since 2023/10/16
 */
@Slf4j
public class CommonFormOfficeForAdminUtils {

    public static final String APPLICATION_ADMIN = "admin";// web管理系统标识

    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 时间格式

    public static final SimpleDateFormat SDF_START = new SimpleDateFormat("yyyy-MM-dd 00:00:00");// 开始时间格式

    public static final String SECURITY_CHECK_TIMEOUT = "security_check_timeout";//超时时间
    public static final String SERVICE_ARGS = "service_args";// 服务参数配置
    public static final int TIME_OUT = Integer.parseInt(CommonFormOfficeForAdminUtils.getServiceArgs().get(CommonFormOfficeForAdminUtils.SECURITY_CHECK_TIMEOUT));// 超时时间

    @Inject
    private SysOssService sysOssService;

    public static String getTempFilePath(String fileName) {
        if (StringUtils.isBlank(fileName)) {
            fileName = ExcelTypeEnum.XLSX.getValue();
        }

        String osName = System.getProperty("os.name");

        String tempFilePath = "/tempFileDir/admin/" + fileName;
        String path = "";
        if (osName.startsWith("Windows")) {
            String filePathStr = "templet/formSummary";
            path = ClassLoader.getSystemResource(filePathStr).getPath() + tempFilePath;
        } else {
            Ioc ioc = NutzIocUtils.getIoc();
            PropertiesProxy propertiesProxy = ioc.getByType(PropertiesProxy.class);
            String projectPath = propertiesProxy.get("cusconfig.project-path");
            path = projectPath + "/file/formSummaryTemplate/" + tempFilePath;
        }
        return path;
    }


    /**
     * 批量压缩文件
     *
     * @param zipOutName   压缩后的文件名称
     * @param fileNameList 待文件列表
     **/
    public static void compressFileList(String zipOutName, List<String> fileNameList) throws IOException, ExecutionException, InterruptedException {
        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("dfxy-compressFileList-pool-").build();
        ExecutorService executor = new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20), factory);
        ParallelScatterZipCreator parallelScatterZipCreator = new ParallelScatterZipCreator(executor);
        OutputStream outputStream = new FileOutputStream(zipOutName);
        ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(outputStream);
        zipArchiveOutputStream.setEncoding("UTF-8");
        for (String fileName : fileNameList) {
            File inFile = new File(fileName);
            final InputStreamSupplier inputStreamSupplier = () -> {
                try {
                    return new FileInputStream(inFile);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    return new NullInputStream(0);
                }
            };
            ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(inFile.getName());
            zipArchiveEntry.setMethod(ZipArchiveEntry.DEFLATED);
            zipArchiveEntry.setSize(inFile.length());
            zipArchiveEntry.setUnixMode(UnixStat.FILE_FLAG | 436);
            parallelScatterZipCreator.addArchiveEntry(zipArchiveEntry, inputStreamSupplier);
        }
        parallelScatterZipCreator.writeTo(zipArchiveOutputStream);
        zipArchiveOutputStream.close();
        outputStream.close();
    }

    /**
     * 上传至华为云服务器
     *
     * @param fileName 文件全路径名称
     */
    public static SysOss uploadFile(File file, String fileName) {
        SysOssService sysOssService = (SysOssService) NutzIocUtils.getBeanByType(SysOssService.class);
        return sysOssService.upload(file, fileName);
    }

    /**
     * 获取本地服务器图片文件夹路径
     */
    public static String getTempParentPictureFile(String fileName) {
        String osName = System.getProperty("os.name");
        String tempFilePath = "/tempPicPath" + fileName;
        String path = "";
        if (osName.startsWith("Windows")) {
            String filePathStr = "templet/formSummary";
            path = ClassLoader.getSystemResource(filePathStr).getPath() + tempFilePath;
            if (StringUtils.isNotEmpty(path) && path.startsWith("/")) {
                path = path.substring(1); // 移除首个斜杠
            }
        } else {
            Ioc ioc = NutzIocUtils.getIoc();
            PropertiesProxy propertiesProxy = ioc.getByType(PropertiesProxy.class);
            String projectPath = propertiesProxy.get("cusconfig.project-path");
            path = projectPath + "/file" + tempFilePath;
        }
        return path;
    }

    /**
     * 下载图片时，先去缓存里面找，没有再去下载
     * @return InputStream
     */
    public static InputStream downloadPictureCache(String pathUrl) {
        InputStream inputStream = null;
        try {
            long startTime = System.currentTimeMillis();
            if (StringUtils.isNotBlank(pathUrl)) {
                String localFilePath = CommonFormOfficeForAdminUtils.getTempParentPictureFile(pathUrl);
                Path path = Paths.get(localFilePath);
                if (Files.exists(path)) {
                    inputStream = new FileInputStream(localFilePath);
                } else {
                    log.info("downloadPictureCache 需要远程下载的图片： {}", pathUrl);
                    if (StringUtils.isNotEmpty(pathUrl) && pathUrl.startsWith("/")) {
                        SysOssService sysOssServiceBean = (SysOssService) NutzIocUtils.getBeanByType(SysOssService.class);
                        inputStream = sysOssServiceBean.download(pathUrl);
                    }
                }
                log.info("downloadPictureCache 结束下载图片耗时： {}ms", (System.currentTimeMillis() - startTime));
            }
        } catch (Exception e) {
            log.info("downloadPictureCache 下载图片异常： {}", e.getMessage());
        }
        return inputStream;
    }

    /**
     * 获取服务数据字典
     * @return
     */
    public static Map<String, String> getServiceArgs() {
        return CommonComponent.getDictMap(SERVICE_ARGS);
    }

    /**
     * 上传图片时，先去缓存里面找是否有，没有的话将图片缓存一份
     * @return tempFile 文件流
     * @return savePath 存储路径
     */
    public static void savePictureCache(TempFile tempFile, String savePath) throws IOException {
        if (ObjectUtil.isEmpty(tempFile)) {
            return;
        }
        if (!savePath.endsWith(".png") && !savePath.endsWith(".jpg")) {
            return;
        }
        BufferedOutputStream bos = null;
        try {
            long startTime = System.currentTimeMillis();
            if (StringUtils.isNotEmpty(savePath)) {
                // 检查本地路径是否存在，如果不存在则创建对应的目录
                String localFilePath = CommonFormOfficeForAdminUtils.getTempParentPictureFile(savePath);
                Path path = Paths.get(localFilePath);
                if (Files.exists(path)) {
                    return;
                } else {
                    Path picAbsPath = Paths.get(localFilePath);
                    if (null != picAbsPath.getParent() && Files.notExists(picAbsPath.getParent())) {
                        // 创建所有的父目录
                        Files.createDirectories(picAbsPath.getParent());
                    }
                    bos = new BufferedOutputStream(new FileOutputStream(localFilePath));
                    // 将数据写入文件流
                    bos.write(tempFile.getInputStream().readAllBytes());
                }
            }
            log.info("savePictureCache 缓存图片耗时： {},{}ms", savePath, (System.currentTimeMillis() - startTime));
        } catch (IOException ioException) {
            log.info("savePictureCache IOException： {}", ioException.getMessage());
        } catch (Exception e) {
            log.info("savePictureCache Exception： {}", e.getMessage());
        } finally {
            // 关闭文件流，释放资源
            bos.close();
        }
    }

    public static void main(String[] args) {
        File file=new File("D:\\project\\dfxy-community-xjw\\dfxy-shequ\\1.txt");
    }
}
